`include "../define.svh"

module round (
    // 输入信号
    input [1:0] data_type,      // 数据类型：`FP16或`FP32
    input [47:0] m_in,          // 输入尾数（保留扩展位）
    input signed [9:0] e_in,    // 输入指数
    // 输出信号
    output  [23:0] m_out,    // 舍入后尾数（隐含1.xxx格式）
    output signed [9:0] e_out // 调整后指数
);

// -------------------------------------------------------------------
// 内部信号定义
// -------------------------------------------------------------------
wire [10:0] m_high_16;          // FP16有效尾数（1.xxxx格式，共11位）
wire [23:0] m_high_32;          // FP32有效尾数（1.xxxx格式，共24位）
wire [23:0] m_high;             // 根据数据类型选择的有效尾数
wire guard_bit;                 // 保护位（Guard bit, G）
wire sticky_bit;                // 粘滞位（Sticky bit, S）
wire round_nearest;             // 向偶数舍入条件
wire mant_carry;                // 舍入导致尾数进位
wire is_denormal;               // 当前是否为非规格化数
wire [9:0] shift_amount;        // 非规格化数右移位数
reg [47:0] m_shifted;           // 移位后的尾数（含扩展位）
wire [24:0] m_rounded;           // 舍入后的尾数

// -------------------------------------------------------------------
// 1. 有效尾数提取与GRS位计算
// -------------------------------------------------------------------
assign m_high_16 = m_in[47:37];      // FP16: 取高11位（1.xxxx）
assign m_high_32 = m_in[47:24];      // FP32: 取高24位（1.xxxx）
assign m_high = (data_type == `FP16) ? {13'd0, m_high_16} : m_high_32;

// 提取保护位（G）和粘滞位（S）
assign guard_bit = (data_type == `FP16) ? m_in[36] : m_in[23];
assign sticky_bit = (data_type == `FP16) ? (|m_in[35:26]) : (|m_in[22:0]);

// -------------------------------------------------------------------
// 2. 向偶数舍入条件判断
// -------------------------------------------------------------------
assign round_nearest = guard_bit & (sticky_bit | m_high[0]); // G && (R || S)

// -------------------------------------------------------------------
// 3. 规格化/非规格化判断
// -------------------------------------------------------------------
assign is_denormal = (e_in < 10'sd1);

// -------------------------------------------------------------------
// 4. 非规格化数移位处理
// -------------------------------------------------------------------
assign shift_amount = 10'sd1 - e_in;

always @(*) begin
    if (is_denormal) begin
        // 非规格化数右移，保留扩展位
        case (data_type)
            `FP16: m_shifted = {24'b0, m_in[47:26]} >> shift_amount; // FP16右移
            `FP32: m_shifted = m_in >> shift_amount;                // FP32右移
            default: m_shifted = m_in;
        endcase
    end else begin
        m_shifted = m_in; // 规格化数不移位
    end
end

// -------------------------------------------------------------------
// 5. 尾数舍入与指数调整
// -------------------------------------------------------------------
// 舍入操作：若需要进位，尾数+1
assign m_rounded = m_high + round_nearest;

// 判断是否因进位导致尾数溢出（例如1.111... → 10.000...）
assign mant_carry = (data_type == `FP16) ? m_rounded[11] : m_rounded[24];

// 指数调整逻辑
wire signed [9:0] e_adjusted;
assign e_adjusted = 
    is_denormal ? 10'sd0 :               // 非规格化数指数强制为0
    (mant_carry ? e_in + 10'sd1 : e_in); // 规格化数进位则指数+1

// 尾数调整逻辑
wire [23:0] m_adjusted;
assign m_adjusted = (data_type == `FP16) ? 
                   (mant_carry ? {1'b1, 10'd0} : m_rounded[10:0]) :  // FP16: 进位时右移一位
                   (mant_carry ? {1'b1, 23'd0} : m_rounded[23:0]);   // FP32: 进位时右移一位

// 非规格化数尾数处理
wire [23:0] m_denormal;
assign m_denormal = (data_type == `FP16) ? 
                   {13'd0, m_shifted[21:11]} :  // FP16: 取移位后的高11位
                   m_shifted[47:24];            // FP32: 取移位后的高24位

// -------------------------------------------------------------------
// 6. 输出寄存与异常标志
// -------------------------------------------------------------------
    assign m_out = is_denormal ? m_denormal : m_adjusted;  // 根据是否为非规格化数选择输出
    assign e_out = e_adjusted;

endmodule